package com.ts.api.module.api.service.impl;

import com.gitee.apanlh.util.algorithm.digest.MD5;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Empty;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.reflection.CopyUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.ts.api.common.constant.channel.ChannelIsRegisterEnum;
import com.ts.api.common.localcache.DistrictCache;
import com.ts.api.module.api.convert.core.annotation.ApiChannelMarketConvertType;
import com.ts.api.module.api.convert.core.entity.ApiBizStatus;
import com.ts.api.module.api.convert.market.context.ApiChannelMarketConvertContext;
import com.ts.api.module.api.convert.market.entity.ChannelMarketParameter;
import com.ts.api.module.api.convert.market.handler.ChannelMarketConvertHandler;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiCheckHistoryUserBO;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiChannelMarketService;
import com.ts.api.module.channel.entity.po.ChannelPO;
import com.ts.api.module.channel.entity.po.ChannelUserFormPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.entity.qo.ChannelUserQO;
import com.ts.api.module.channel.service.ChannelUserService;
import com.ts.api.module.channel.service.DoubleWriteUserService;
import com.ts.api.module.common.entity.DistrictPO;
import com.ts.api.module.match.market.ChannelMarketMatchFacade;
import com.ts.cache.form.FormCacheService;
import com.ts.cache.form.entity.FormCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Service
public class ApiChannelMarketServiceImpl implements ApiChannelMarketService {

    @Autowired
    private ChannelUserService channelUserService;
    @Autowired
    private ApiChannelMarketConvertContext apiChannelMarketConvertContext;
    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private DoubleWriteUserService doubleWriteUserService;
    @Autowired
    private FormCacheService formCacheService;
    @Autowired
    private ChannelMarketMatchFacade channelMarketMatchFacade;

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> existUserByMd5(ChannelPO channelPO, RequestVO requestVO) {
        ChannelMarketConvertHandler channelMarketConvertHandler = apiChannelMarketConvertContext.getChannelMarket(channelPO, ApiChannelMarketConvertType.DATA_EXCHANGE_MD5);
        ApiUserRequest apiUserRequest = channelMarketConvertHandler.parse(requestVO);

        String phone = apiUserRequest.getPhone();
        String phoneMd5 = apiUserRequest.getPhoneMd5();

        if (ValidParam.isNotEmpty(phone)) {
            apiUserRequest.setPhoneMd5(MD5.create().digestToHex(phone));
        }

        if (ValidParam.isEmpty(phoneMd5)) {
            return channelMarketConvertHandler.response(null, ApiBizStatus.fail("非法md5"));
        }

        ApiCheckHistoryUserBO channelCheckHistoryBO = ApiCheckHistoryUserBO.createChannelByMd5(channelPO, phoneMd5);
        boolean existHistory = apiBizRequiredService.existHistoryUser(channelCheckHistoryBO);
        boolean existLocal = channelUserService.hasLocalExist(phoneMd5);

        if (existHistory || existLocal) {
            return channelMarketConvertHandler.response(null, ApiBizStatus.fail("已存在"));
        }
        return channelMarketConvertHandler.response(null, ApiBizStatus.suc());
    }

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> existUserPhoneMask(ChannelPO channelPO, RequestVO requestVO, int matchSize, ApiChannelMarketConvertType apiChannelMarketConvertType) {
        ChannelMarketConvertHandler channelMarketConvertHandler = apiChannelMarketConvertContext.getChannelMarket(channelPO, apiChannelMarketConvertType);
        ApiUserRequest apiUserRequest = channelMarketConvertHandler.parse(requestVO);

        String phone = apiUserRequest.getPhone();
        if (ValidParam.isEmpty(phone)) {
            return channelMarketConvertHandler.response(null, ApiBizStatus.fail("非法掩码号"));
        }

        //  返回实体
        ChannelMarketParameter channelMarketParameter = new ChannelMarketParameter();
        MD5 md5 = MD5.create();
        List<String> listPhoneMd5 = CollUtils.newArrayList();

        //  搜索老库手机号掩码
        ApiCheckHistoryUserBO channelByPhoneMask = ApiCheckHistoryUserBO.createChannelByPhoneMask(channelPO, phone);
        List<ChannelUserRegisterPO> listHistoryMatchUser = apiBizRequiredService.existHistoryUserPhoneMask(channelByPhoneMask);

        //  右匹配查询
        String subPhone = phone.substring(0, matchSize);
        ChannelUserQO channelUserQO = ChannelUserQO.createPhone(subPhone);
        List<ChannelUserRegisterPO> listMatchUser = channelUserService.listRightMatchPhone(channelUserQO);
        //  如果不存在则直接返回可匹配
        if (ValidParam.isEmpty(listMatchUser) && ValidParam.isEmpty(listHistoryMatchUser)) {
            channelMarketParameter.setListPhoneMd5(Empty.list());
            return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
        }

        //  添加新库
        IteratorUtils.array(listMatchUser, t -> listPhoneMd5.add(md5.digestToHex(t.getPhone())));
        //  添加历史库
        IteratorUtils.array(listHistoryMatchUser, t -> listPhoneMd5.add(md5.digestToHex(t.getPhone())));

        //  去重
        List<String> listDistinct = CollUtils.newHashSet(listPhoneMd5).stream().toList();

        //  如果存在将存在的手机md5返回
        channelMarketParameter.setListPhoneMd5(listDistinct);
        return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
    }

    @Override
    public Map<String, Object> existUserForm(ChannelPO channelPO, RequestVO requestVO) {
        ChannelMarketConvertHandler channelMarketConvertHandler = apiChannelMarketConvertContext.getChannelMarket(channelPO, ApiChannelMarketConvertType.DATA_EXCHANGE_FORM);
        //  需要资质映射
        ApiUserRequest apiUserRequest = channelMarketConvertHandler.parse(requestVO);

        String phone = apiUserRequest.getPhone();
        String phoneMd5 = apiUserRequest.getPhoneMd5();

        if (ValidParam.isNotEmpty(phone)) {
            apiUserRequest.setPhoneMd5(MD5.create().digestToHex(phone));
            ApiCheckHistoryUserBO channelCheckHistoryBO = ApiCheckHistoryUserBO.createChannelByMd5(channelPO, phoneMd5);
            boolean existHistory = apiBizRequiredService.existHistoryUser(channelCheckHistoryBO);
            boolean existLocal = channelUserService.hasLocalExist(phoneMd5);

            if (existHistory || existLocal) {
                return channelMarketConvertHandler.response(null, ApiBizStatus.fail("撞库失败,已存在"));
            }
        }

        //  添加资质校验实体
        ApiUserRequest copyUserRequest = CopyUtils.copy(apiUserRequest, ApiUserRequest.class);
        ChannelMarketParameter channelMarketParameter = new ChannelMarketParameter();
        channelMarketParameter.setApiUserRequest(copyUserRequest);
        //  资质响应返回
        return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
    }

    @Override
    public Map<String, Object> federateLogin(ChannelPO channelPO, RequestVO requestVO) {
        ChannelMarketConvertHandler channelMarketConvertHandler = apiChannelMarketConvertContext.getChannelMarket(channelPO, ApiChannelMarketConvertType.FEDERATE_LOGIN);
        ApiUserRequest apiUserRequest = channelMarketConvertHandler.parse(requestVO);
        String phone = apiUserRequest.getPhone();

        if (ValidParam.isNotEmpty(phone)) {
            apiUserRequest.setPhoneMd5(MD5.create().digestToHex(phone));
        }

        //  参数检测
        if (ValidParam.isEmpty(apiUserRequest.getPhone()) && ValidParam.isEmpty(apiUserRequest.getPhoneMd5())) {
            return channelMarketConvertHandler.response(null, ApiBizStatus.fail("非法联登参数"));
        }

        //  检测用户
        ChannelUserRegisterPO channelUserRegisterPO;
        if (ValidParam.isEmpty(apiUserRequest.getPhoneMd5())) {
            //  手机号md5
            channelUserRegisterPO = channelUserService.get(ChannelUserQO.createPhoneMd5(apiUserRequest.getPhoneMd5()));
        } else {
            //  手机号明文
            channelUserRegisterPO = channelUserService.get(ChannelUserQO.createPhone(apiUserRequest.getPhone()));
        }

        //  返回消息实体
        ChannelMarketParameter channelMarketParameter = new ChannelMarketParameter();

        //  如果渠道是下游跳转模式则改变url路径
        if (ApiChannelMarketConvertType.FEDERATE_TO_CONSUMER_MARKET.getType().equals(channelPO.getApiFederateType())) {
            //  匹配下游贷超联登
            channelMarketParameter.setUrl(channelPO.getLink() + "&federateToConsumer=" + apiUserRequest.getPhoneMd5());
        } else  {
            //  普通表单联登
            channelMarketParameter.setUrl(channelPO.getLink() + "&federate=" + apiUserRequest.getPhoneMd5());
        }

        //  如果存在用户则直接返回联登用户
        if (ValidParam.isNotNull(channelUserRegisterPO)) {
            //  更新老用户标识
            ChannelUserRegisterPO updateUser = new ChannelUserRegisterPO();
            updateUser.setId(channelUserRegisterPO.getId());
            updateUser.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
            channelUserService.update(updateUser);

            return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
        }

        //  注册用户
        ChannelUserRegisterPO registerPO = new ChannelUserRegisterPO();
        registerPO.setPhone(apiUserRequest.getPhone());
        registerPO.setPhoneMd5(apiUserRequest.getPhoneMd5());
        registerPO.setLoanChannelId(channelPO.getId());
        registerPO.setCreateTime(DateUtils.currentTime());
        if (ValidParam.isNotEmpty(apiUserRequest.getCity())) {
            DistrictPO districtPO = DistrictCache.getByName(apiUserRequest.getCity());
            registerPO.setAreaName(districtPO.getName());
            registerPO.setAreaCode(districtPO.getCode());
        }

        //  并发处理
        try {
            doubleWriteUserService.insertUser(registerPO);
        } catch (DuplicateKeyException e) {
            //  即使重复页返回H5页面链接
        }

        //  返回链接
        return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
    }

    @Override
    public Map<String, Object> federateUserForm(ChannelPO channelPO, RequestVO requestVO) {
        ChannelMarketConvertHandler channelMarketConvertHandler = apiChannelMarketConvertContext.getChannelMarket(channelPO, ApiChannelMarketConvertType.FEDERATE_USER_FORM);
        //  需要资质映射
        ApiUserRequest apiUserRequest = channelMarketConvertHandler.parse(requestVO);

        String phone = apiUserRequest.getPhone();

        if (ValidParam.isNotEmpty(phone)) {
            apiUserRequest.setPhoneMd5(MD5.create().digestToHex(phone));
        }

        //  参数检测
        if (ValidParam.isEmpty(apiUserRequest.getPhone()) && ValidParam.isEmpty(apiUserRequest.getPhoneMd5())) {
            return channelMarketConvertHandler.response(null, ApiBizStatus.fail("非法联登参数"));
        }

        //  检测用户
        ChannelUserRegisterPO channelUserRegisterPO;
        if (ValidParam.isEmpty(apiUserRequest.getPhoneMd5())) {
            //  手机号md5
            channelUserRegisterPO = channelUserService.get(ChannelUserQO.createPhoneMd5(apiUserRequest.getPhoneMd5()));
        } else {
            //  手机号明文
            channelUserRegisterPO = channelUserService.get(ChannelUserQO.createPhone(apiUserRequest.getPhone()));
        }

        //  转换用户表单信息
        List<FormCache> listFormCache = formCacheService.get();
        List<ChannelUserFormPO> listUserForm = apiUserRequest.toListUserForm(listFormCache);

        //  返回消息实体
        ChannelMarketParameter channelMarketParameter = new ChannelMarketParameter();
        String link = channelPO.getLink();

        //  如果存在用户则直接返回联登用户
        if (ValidParam.isNotNull(channelUserRegisterPO)) {
            //  更新老用户标识
            ChannelUserRegisterPO updateUser = new ChannelUserRegisterPO();
            updateUser.setId(channelUserRegisterPO.getId());
            updateUser.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
            channelUserService.update(updateUser);

            //  更新用户表单
            doubleWriteUserService.removeByUserId(channelUserRegisterPO.getId());
            //  设置表单用户信息
            IteratorUtils.array(listUserForm, item -> {
                item.setChannelId(channelUserRegisterPO.getLoanChannelId());
                item.setUserId(channelUserRegisterPO.getId());
                item.setCreateTime(DateUtils.currentTime());
            });
            doubleWriteUserService.batchInsertUserForm(listUserForm);

            channelMarketParameter.setUrl(link + "&federate=" + apiUserRequest.getPhoneMd5());
            return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
        }

        //  注册用户信息
        ChannelUserRegisterPO registerPO = new ChannelUserRegisterPO();
        registerPO.setPhone(apiUserRequest.getPhone());
        registerPO.setPhoneMd5(apiUserRequest.getPhoneMd5());
        registerPO.setLoanChannelId(channelPO.getId());
        registerPO.setCreateTime(DateUtils.currentTime());
        if (ValidParam.isNotEmpty(apiUserRequest.getCity())) {
            DistrictPO districtPO = DistrictCache.getByName(apiUserRequest.getCity());
            registerPO.setAreaName(districtPO.getName());
            registerPO.setAreaCode(districtPO.getCode());
        }

        //  并发处理
        try {
            ChannelUserRegisterPO insertUser = doubleWriteUserService.insertUser(registerPO);
            //  设置表单用户信息
            IteratorUtils.array(listUserForm, item -> {
                item.setChannelId(insertUser.getLoanChannelId());
                item.setUserId(insertUser.getId());
                item.setCreateTime(DateUtils.currentTime());
            });
            doubleWriteUserService.batchInsertUserForm(listUserForm);
        } catch (DuplicateKeyException e) {
            //  即使重复页返回H5页面链接
        }

        //  返回链接-需要生成渠道号
        channelMarketParameter.setUrl(link + "&federate=" + apiUserRequest.getPhoneMd5());
        return channelMarketConvertHandler.response(channelMarketParameter, ApiBizStatus.suc());
    }
}
